package com.asen.libcommon.http

//import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import com.asen.libcommon.base.BaseApplication
import com.asen.libcommon.config.BaseConfig
import com.asen.libcommon.http.interceptor.*
import com.asen.libcommon.http.livedata.LiveDataCallAdapterFactory
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.moshi.MoshiConverterFactory
import java.io.File
import java.util.concurrent.TimeUnit

/**
 * @date   : 2021/1/18
 * @author : asenLiang
 * @e-mail : liangAisiSen@163.com
 * @desc   : Retrofit 网络封装
 */
abstract class RetrofitFactory<T> {

    var service: T?

    abstract fun service(): Class<T>

    init {
        service = Code.getRetrofit()?.create(this.service()) /* 获取 Retrofit ，全局只有一个 */
    }

    private class Code {

        companion object {

            private var retrofit: Retrofit? = null

            /** 实例化 Retrofit */
            fun getRetrofit(): Retrofit? {
                if (retrofit == null) {
                    synchronized(RetrofitFactory::class.java) {
                        if (retrofit == null) {
                            retrofit = Retrofit.Builder()
                                .baseUrl(HttpConfig.debugUrl)
                                //.addConverterFactory(GsonConverterFactory.create())      // TODO:反序列化json格式的时候如果没有该字段直接变成空，把默认值删除掉了（无默认值空安全）
                                .addConverterFactory(MoshiConverterFactory.create())       // TODO:在kotlin中推荐使用moshi，对 Kt 非常友好，反序列化json字段没有的会保留默认值（有默认值空安全）
                                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // TODO:rxJava 使用Observable<T>接收返回结果
                                //.addCallAdapterFactory(CoroutineCallAdapterFactory())    // TODO:携程(Retrofit 2.4.0的使用方式)：使用Deferred<T>返回结果，现在改用2.6.0之后的版本直接使用 suspend 关键字挂起函数进行请求
                                .addCallAdapterFactory(LiveDataCallAdapterFactory())       // TODO:LiveData<T>返回
                                .client(initClient())
                                .build()
                        }
                    }
                }
                return retrofit
            }

            /** 获取 OkHttpClient 实例对象 */
            private fun initClient(): OkHttpClient {

                val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
                    level =
                        if (BaseConfig.isDebug) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.HEADERS
                }

                /* 设置 请求的缓存的大小跟位置 */
                val cacheFile = File(BaseApplication.application.cacheDir, "cache")
                val cache = Cache(cacheFile, HttpConfig.MAX_CACHE_SIZE)

                return OkHttpClient().newBuilder().run {
                    addInterceptor(LocalBaseUrlInterceptor())    // 本地 debug/release/第三方 的 baseUrl 拦截设置
                    addInterceptor(httpLoggingInterceptor)       // 日志输出
                    addInterceptor(LoggerInterceptor())          // 日志,所有的请求响应
                    addInterceptor(CommonParameterInterceptor()) // 公用参数 拦截设置
                    addInterceptor(HeaderInterceptor())          // 头部拦截设置
                    addInterceptor(CookieInterceptor())          // Cookie 拦截设置
                    addInterceptor(CacheInterceptor())           // 缓存设置
                    addInterceptor(ErrorInterceptor())           // 错误设置
                    cache(cache)                                 // 添加缓存
                    connectTimeout(HttpConfig.DEFAULT_TIMEOUT, TimeUnit.SECONDS) // 连接超时时长 设置
                    readTimeout(HttpConfig.DEFAULT_TIMEOUT, TimeUnit.SECONDS)    // 读取时长 设置
                    writeTimeout(HttpConfig.DEFAULT_TIMEOUT, TimeUnit.SECONDS)   // 写时长 设置
                    retryOnConnectionFailure(true)        // 错误重连 设置
                    // cookieJar(CookieManager())
                }.build()
            }

        }
    }


}